package com.ciwong.epaper.util.KHBVideo;

import java.lang.reflect.Method;
import java.util.Map;

import com.ciwong.libs.utils.CWLog;

import android.graphics.Point;
import android.graphics.SurfaceTexture;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Looper;
import android.os.Message;
import android.view.Surface;
import android.view.TextureView;

/**
 * <p>
 * 统一管理MediaPlayer的地方,只有一个mediaPlayer实例，那么不会有多个视频同时播放，也节省资源。
 * </p>
 * <p>
 * Unified management MediaPlayer place, there is only one MediaPlayer instance,
 * then there will be no more video broadcast at the same time, also save
 * resources.
 * </p>
 * Created by PLA-BYOU on 2017/10/31.
 */
public class KHBMediaManager implements TextureView.SurfaceTextureListener,
        MediaPlayer.OnPreparedListener, MediaPlayer.OnCompletionListener,
        MediaPlayer.OnBufferingUpdateListener,
        MediaPlayer.OnSeekCompleteListener, MediaPlayer.OnErrorListener,
        MediaPlayer.OnInfoListener, MediaPlayer.OnVideoSizeChangedListener
{
    public static final int HANDLER_PREPARE = 0;

    public static final int HANDLER_RELEASE = 2;

    public static final String TAG = "KHBMediaManager";

    public static KHBResizeTextureView textureView;

    public static SurfaceTexture savedSurfaceTexture;

    public static Surface surface;

    public static String CURRENT_PLAYING_URL;

    public static boolean CURRENT_PLING_LOOP;

    public static Map<String, String> MAP_HEADER_DATA;

    private static KHBMediaManager khbMediaManager;

    public MediaPlayer mediaPlayer = new MediaPlayer();

    public int currentVideoWidth = 0;

    public int currentVideoHeight = 0;

    HandlerThread mMediaHandlerThread;

    MediaHandler mMediaHandler;

    Handler mainThreadHandler;

    public int positionInList = -1;

    public KHBMediaManager()
    {
        mMediaHandlerThread = new HandlerThread(TAG);
        mMediaHandlerThread.start();
        mMediaHandler = new MediaHandler((mMediaHandlerThread.getLooper()));
        mainThreadHandler = new Handler();
    }

    public static KHBMediaManager instance()
    {
        if (khbMediaManager == null)
        {
            khbMediaManager = new KHBMediaManager();
        }
        return khbMediaManager;
    }

    public Point getVideoSize()
    {
        if (currentVideoWidth != 0 && currentVideoHeight != 0)
        {
            return new Point(currentVideoWidth, currentVideoHeight);
        }
        else
        {
            return null;
        }
    }

    public void prepare()
    {
        releaseMediaPlayer();
        Message msg = new Message();
        msg.what = HANDLER_PREPARE;
        mMediaHandler.sendMessage(msg);
    }

    public void releaseMediaPlayer()
    {
        Message msg = new Message();
        msg.what = HANDLER_RELEASE;
        mMediaHandler.sendMessage(msg);
    }

    @Override
    public void onSurfaceTextureAvailable(SurfaceTexture surfaceTexture, int i,
                                          int i1)
    {
        CWLog.i(TAG, "onSurfaceTextureAvailable ["
                + KHBVideoPlayerManager.getCurrentJzvd().hashCode() + "] ");
        if (savedSurfaceTexture == null)
        {
            savedSurfaceTexture = surfaceTexture;
            prepare();
        }
        else
        {
            textureView.setSurfaceTexture(savedSurfaceTexture);
        }
    }

    @Override
    public void onSurfaceTextureSizeChanged(SurfaceTexture surfaceTexture,
                                            int i, int i1)
    {
        // 如果SurfaceTexture还没有更新Image，则记录SizeChanged事件，否则忽略
        CWLog.i(TAG, "onSurfaceTextureSizeChanged ["
                + KHBVideoPlayerManager.getCurrentJzvd().hashCode() + "] ");
    }

    @Override
    public boolean onSurfaceTextureDestroyed(SurfaceTexture surfaceTexture)
    {
        return savedSurfaceTexture == null;
    }

    @Override
    public void onSurfaceTextureUpdated(SurfaceTexture surfaceTexture)
    {
    }

    @Override
    public void onPrepared(MediaPlayer mp)
    {
        mediaPlayer.start();
        mainThreadHandler.post(new Runnable()
        {
            @Override
            public void run()
            {
                if (KHBVideoPlayerManager.getCurrentJzvd() != null)
                {
                    KHBVideoPlayerManager.getCurrentJzvd().onPrepared();
                }
            }
        });
    }

    @Override
    public void onCompletion(MediaPlayer mp)
    {
        mainThreadHandler.post(new Runnable()
        {
            @Override
            public void run()
            {
                if (KHBVideoPlayerManager.getCurrentJzvd() != null)
                {
                    KHBVideoPlayerManager.getCurrentJzvd().onAutoCompletion();
                }
            }
        });
    }

    @Override
    public void onBufferingUpdate(MediaPlayer mp, final int percent)
    {
        mainThreadHandler.post(new Runnable()
        {
            @Override
            public void run()
            {
                if (KHBVideoPlayerManager.getCurrentJzvd() != null)
                {
                    KHBVideoPlayerManager.getCurrentJzvd()
                            .setBufferProgress(percent);
                }
            }
        });
    }

    @Override
    public void onSeekComplete(MediaPlayer mp)
    {
        mainThreadHandler.post(new Runnable()
        {
            @Override
            public void run()
            {
                if (KHBVideoPlayerManager.getCurrentJzvd() != null)
                {
                    KHBVideoPlayerManager.getCurrentJzvd().onSeekComplete();
                }
            }
        });
    }

    @Override
    public boolean onError(MediaPlayer mp, final int what, final int extra)
    {
        mainThreadHandler.post(new Runnable()
        {
            @Override
            public void run()
            {
                if (KHBVideoPlayerManager.getCurrentJzvd() != null)
                {
                    KHBVideoPlayerManager.getCurrentJzvd().onError(what, extra);
                }
            }
        });
        return true;
    }

    @Override
    public boolean onInfo(MediaPlayer mp, final int what, final int extra)
    {
        mainThreadHandler.post(new Runnable()
        {
            @Override
            public void run()
            {
                if (KHBVideoPlayerManager.getCurrentJzvd() != null)
                {
                    KHBVideoPlayerManager.getCurrentJzvd().onInfo(what, extra);
                }
            }
        });
        return false;
    }

    @Override
    public void onVideoSizeChanged(MediaPlayer mp, int width, int height)
    {
        currentVideoWidth = width;
        currentVideoHeight = height;
        mainThreadHandler.post(new Runnable()
        {
            @Override
            public void run()
            {
                if (KHBVideoPlayerManager.getCurrentJzvd() != null)
                {
                    KHBVideoPlayerManager.getCurrentJzvd().onVideoSizeChanged();
                }
            }
        });
    }

    public class MediaHandler extends Handler
    {
        public MediaHandler(Looper looper)
        {
            super(looper);
        }

        @Override
        public void handleMessage(Message msg)
        {
            super.handleMessage(msg);
            switch (msg.what)
            {
                case HANDLER_PREPARE:
                    try
                    {
                        currentVideoWidth = 0;
                        currentVideoHeight = 0;
                        mediaPlayer.release();
                        mediaPlayer = new MediaPlayer();
                        mediaPlayer
                                .setAudioStreamType(AudioManager.STREAM_MUSIC);
                        mediaPlayer.setLooping(CURRENT_PLING_LOOP);
                        mediaPlayer.setOnPreparedListener(KHBMediaManager.this);
                        mediaPlayer
                                .setOnCompletionListener(KHBMediaManager.this);
                        mediaPlayer.setOnBufferingUpdateListener(
                                KHBMediaManager.this);
                        mediaPlayer.setScreenOnWhilePlaying(true);
                        mediaPlayer
                                .setOnSeekCompleteListener(KHBMediaManager.this);
                        mediaPlayer.setOnErrorListener(KHBMediaManager.this);
                        mediaPlayer.setOnInfoListener(KHBMediaManager.this);
                        mediaPlayer.setOnVideoSizeChangedListener(
                                KHBMediaManager.this);
                        Class<MediaPlayer> clazz = MediaPlayer.class;
                        Method method = clazz.getDeclaredMethod("setDataSource",
                                String.class, Map.class);
                        method.invoke(mediaPlayer, CURRENT_PLAYING_URL,
                                MAP_HEADER_DATA);
                        mediaPlayer.prepareAsync();
                        if (surface != null)
                        {
                            surface.release();
                        }
                        surface = new Surface(savedSurfaceTexture);
                        mediaPlayer.setSurface(surface);
                    }
                    catch (Exception e)
                    {
                        e.printStackTrace();
                    }
                    break;
                case HANDLER_RELEASE:
                    // CURRENT_PLAYING_URL = null;
                    // CURRENT_PLING_LOOP = false;
                    // MAP_HEADER_DATA = null;
                    mediaPlayer.release();
                    break;
            }
        }
    }

}

